/**
 * Copyright (c) 2018-2099, Mr.Z (528486600@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.csg.iotplatform.module.system.util;

import cn.csg.iotplatform.framework.common.pojo.PageResult;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;

import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Stream;

/**
 * @Description 高频方法集合类
 * @Author Mr.Z
 * @Date 2021-07-23 10:16
 * @Version v1.0
 **/
public class ToolUtil {

    /**
     * 格式化日期(yyyy-MM-dd)
     *
     * @param time 日期时间(未去除时分秒)
     * @return 日期时间(去除时分秒)
     */
    public static Date formatDate(Date time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(time);
        Date parse = null;
        try {
            parse = simpleDateFormat.parse(format);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;
    }

    /**
     * 获取开始时间(yyyy-MM-dd HH:mm:ss)
     *
     * @param time
     * @return
     */
    public static Date getStartDate(Date time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(time);
        format = format + " 00:00:00";
        SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date parse = null;
        try {
            parse = simpleDateFormat2.parse(format);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;
    }

    /**
     * 获取结束时间(yyyy-MM-dd HH:mm:ss)
     *
     * @param time
     * @return
     */
    public static Date getEndDate(Date time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(time);
        format = format + " 23:59:59";
        SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date parse = null;
        try {
            parse = simpleDateFormat2.parse(format);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;
    }

    /**
     * 获取随机位数的字符串
     *
     * @author Mr.Z
     * @Date 2017/8/24 14:09
     */
    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 获取随机位数的字符串(数字)
     *
     * @author Mr.Z
     * @Date 2017/8/24 14:09
     */
    public static String getRandomNumber(int length) {
        String base = "0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 获取异常的具体信息
     *
     * @author Mr.Z
     * @Date 2017/3/30 9:21
     * @version 2.0
     */
    public static String getExceptionMsg(Exception e) {
        StringWriter sw = new StringWriter();
        try {
            e.printStackTrace(new PrintWriter(sw));
        } finally {
            try {
                sw.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        return sw.getBuffer().toString().replaceAll("\\$", "T");
    }

    /**
     * 比较两个对象是否相等。<br>
     * 相同的条件有两个，满足其一即可：<br>
     * 1. obj1 == null && obj2 == null; 2. obj1.equals(obj2)
     *
     * @param obj1 对象1
     * @param obj2 对象2
     * @return 是否相等
     */
    public static boolean equals(Object obj1, Object obj2) {
        return (obj1 != null) ? (obj1.equals(obj2)) : (obj2 == null);
    }

    /**
     * 计算对象长度，如果是字符串调用其length函数，集合类调用其size函数，数组调用其length属性，其他可遍历对象遍历计算长度
     *
     * @param obj 被计算长度的对象
     * @return 长度
     */
    public static int length(Object obj) {
        if (obj == null) {
            return 0;
        }
        if (obj instanceof CharSequence) {
            return ((CharSequence) obj).length();
        }
        if (obj instanceof Collection) {
            return ((Collection<?>) obj).size();
        }
        if (obj instanceof Map) {
            return ((Map<?, ?>) obj).size();
        }

        int count;
        if (obj instanceof Iterator) {
            Iterator<?> iter = (Iterator<?>) obj;
            count = 0;
            while (iter.hasNext()) {
                count++;
                iter.next();
            }
            return count;
        }
        if (obj instanceof Enumeration) {
            Enumeration<?> enumeration = (Enumeration<?>) obj;
            count = 0;
            while (enumeration.hasMoreElements()) {
                count++;
                enumeration.nextElement();
            }
            return count;
        }
        if (obj.getClass().isArray() == true) {
            return Array.getLength(obj);
        }
        return -1;
    }

    /**
     * 对象中是否包含元素
     *
     * @param obj     对象
     * @param element 元素
     * @return 是否包含
     */
    public static boolean contains(Object obj, Object element) {
        if (obj == null) {
            return false;
        }
        if (obj instanceof String) {
            if (element == null) {
                return false;
            }
            return ((String) obj).contains(element.toString());
        }
        if (obj instanceof Collection) {
            return ((Collection<?>) obj).contains(element);
        }
        if (obj instanceof Map) {
            return ((Map<?, ?>) obj).values().contains(element);
        }
        if (obj instanceof Iterator) {
            Iterator<?> iter = (Iterator<?>) obj;
            while (iter.hasNext()) {
                Object o = iter.next();
                if (equals(o, element)) {
                    return true;
                }
            }
            return false;
        }
        if (obj instanceof Enumeration) {
            Enumeration<?> enumeration = (Enumeration<?>) obj;
            while (enumeration.hasMoreElements()) {
                Object o = enumeration.nextElement();
                if (equals(o, element)) {
                    return true;
                }
            }
            return false;
        }
        if (obj.getClass().isArray() == true) {
            int len = Array.getLength(obj);
            for (int i = 0; i < len; i++) {
                Object o = Array.get(obj, i);
                if (equals(o, element)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 对象是否不为空(新增)
     *
     * @param o String,List,Map,Object[],int[],long[]
     * @return
     */
    public static boolean isNotEmpty(Object o) {
        return !isEmpty(o);
    }

    /**
     * 对象是否为空
     *
     * @param o String,List,Map,Object[],int[],long[]
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static boolean isEmpty(Object o) {
        if (o == null) {
            return true;
        }
        if (o instanceof String) {
            if (o.toString().trim().equals("")) {
                return true;
            }
        } else if (o instanceof List) {
            if (((List) o).size() == 0) {
                return true;
            }
        } else if (o instanceof Map) {
            if (((Map) o).size() == 0) {
                return true;
            }
        } else if (o instanceof Set) {
            if (((Set) o).size() == 0) {
                return true;
            }
        } else if (o instanceof Object[]) {
            if (((Object[]) o).length == 0) {
                return true;
            }
        } else if (o instanceof int[]) {
            if (((int[]) o).length == 0) {
                return true;
            }
        } else if (o instanceof long[]) {
            if (((long[]) o).length == 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 对象组中是否存在 Empty Object
     *
     * @param os 对象组
     * @return
     */
    public static boolean isOneEmpty(Object... os) {
        for (Object o : os) {
            if (isEmpty(o)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 对象组中是否全是 Empty Object
     *
     * @param os
     * @return
     */
    public static boolean isAllEmpty(Object... os) {
        for (Object o : os) {
            if (!isEmpty(o)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 是否为数字
     *
     * @param obj
     * @return
     */
    public static boolean isNum(Object obj) {
        try {
            Integer.parseInt(obj.toString());
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 如果为空, 则调用默认值
     *
     * @param str
     * @return
     */
    public static Object getValue(Object str, Object defaultValue) {
        if (isEmpty(str)) {
            return defaultValue;
        }
        return str;
    }

    /**
     * 强转->string,并去掉多余空格
     *
     * @param str
     * @return
     */
    public static String toStr(Object str) {
        return toStr(str, "");
    }

    /**
     * 强转->string,并去掉多余空格
     *
     * @param str
     * @param defaultValue
     * @return
     */
    public static String toStr(Object str, String defaultValue) {
        if (null == str) {
            return defaultValue;
        }
        return str.toString().trim();
    }

    /**
     * map的key转为小写
     *
     * @param map
     * @return Map<String, Object>
     */
    public static Map<String, Object> caseInsensitiveMap(Map<String, Object> map) {
        Map<String, Object> tempMap = new HashMap<>();
        for (String key : map.keySet()) {
            tempMap.put(key.toLowerCase(), map.get(key));
        }
        return tempMap;
    }

    /**
     * 获取map中第一个数据值
     *
     * @param <K> Key的类型
     * @param <V> Value的类型
     * @param map 数据源
     * @return 返回的值
     */
    public static <K, V> V getFirstOrNull(Map<K, V> map) {
        V obj = null;
        for (Entry<K, V> entry : map.entrySet()) {
            obj = entry.getValue();
            if (obj != null) {
                break;
            }
        }
        return obj;
    }

    /**
     * 创建StringBuilder对象
     *
     * @return StringBuilder对象
     */
    public static StringBuilder builder(String... strs) {
        final StringBuilder sb = new StringBuilder();
        for (String str : strs) {
            sb.append(str);
        }
        return sb;
    }

    /**
     * 创建StringBuilder对象
     *
     * @return StringBuilder对象
     */
    public static void builder(StringBuilder sb, String... strs) {
        for (String str : strs) {
            sb.append(str);
        }
    }

    /**
     * 去掉指定后缀
     *
     * @param str    字符串
     * @param suffix 后缀
     * @return 切掉后的字符串，若后缀不是 suffix， 返回原字符串
     */
    public static String removeSuffix(String str, String suffix) {
        if (isEmpty(str) || isEmpty(suffix)) {
            return str;
        }
        if (str.endsWith(suffix)) {
            return str.substring(0, str.length() - suffix.length());
        }
        return str;
    }

    /**
     * 判断是否是windows操作系统
     *
     * @author stylefeng
     * @Date 2017/5/24 22:34
     */
    public static Boolean isWinOs() {
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith("win")) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取临时目录
     *
     * @author stylefeng
     * @Date 2017/5/24 22:35
     */
    public static String getTempPath() {
        return System.getProperty("java.io.tmpdir");
    }

    /**
     * 把一个数转化为int
     *
     * @author Mr.Z
     * @Date 2017/11/15 下午11:10
     */
    public static Integer toInt(Object val) {
        if (val instanceof Double) {
            BigDecimal bigDecimal = new BigDecimal((Double) val);
            return bigDecimal.intValue();
        } else {
            return Integer.valueOf(val.toString());
        }
    }

    /**
     * 获取项目路径
     */
    public static String getWebRootPath(String filePath) {
        try {
            String path = ToolUtil.class.getClassLoader().getResource("").toURI().getPath();
            path = path.replace("/WEB-INF/classes/", "");
            path = path.replace("/target/classes/", "");
            path = path.replace("file:/", "");
            if (ToolUtil.isEmpty(filePath)) {
                return path;
            } else {
                return path + "/" + filePath;
            }
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取文件后缀名 不包含点
     */
    public static String getFileSuffix(String fileWholeName) {
        if (ToolUtil.isEmpty(fileWholeName)) {
            return "none";
        }
        int lastIndexOf = fileWholeName.lastIndexOf(".");
        return fileWholeName.substring(lastIndexOf + 1);
    }

// ---------------------------------------------------------------------------------------------------------------------------


    /**
     * 简易版httpPost请求方法
     *
     * @param url      请求url
     * @param paramMap 请求参数
     * @return 响应体
     * @throws Exception
     */
    public static String doHttpPost(String url, Map<String, Object> paramMap, Map<String, String> headMap) throws Exception {
        // String url = "http://www.example.com";
        //1.设置http请求准备
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setRequestMethod("POST"); // 设置请求方法
        conn.setDoOutput(true); // 允许输出数据
        if (isNotEmpty(headMap)) {
            headMap.forEach(conn::setRequestProperty);
        }
        // conn.setRequestProperty("Content-Type", "application/json");
        // conn.setRequestProperty("Authorization", "Bearer " + token);
        conn.connect(); // 连接服务器
        //2.设置http请求参数(post)
        if (isNotEmpty(paramMap)) {
            String jsonData = JSONObject.toJSONString(paramMap); // 请求体数据
            OutputStream os = conn.getOutputStream();
            os.write(jsonData.getBytes());
            os.flush();
            os.close();
        }
        //3.获取请求响应
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line = "";
        while ((line = reader.readLine()) != null) {
            return line; // 输出服务器响应结果
        }
        reader.close();
        conn.disconnect(); // 断开连接
        return line;
    }

    /**
     * 获取参照为今天的某一天日期
     *
     * @param days 相差天数
     * @return 对应的日期
     */
    public static LocalDate getDateOfDays(int days) {
        LocalDate today = LocalDate.now(); //今天为基本
        return today.minus(Period.ofDays(days));
    }

    /**
     * 获取参照为指定日期的所属自然周第一天
     *
     * @param day 日期
     * @return 对应的日期
     */
    public static LocalDate getFirstDayOfWeek(Date day) {
        String[] dayStr = DateUtil.formatDate(day).split("-");
        Integer[] dayInt = Stream.of(dayStr).map(Integer::valueOf).toArray(Integer[]::new);
        Integer y = dayInt[0];
        Integer m = dayInt[1];
        Integer d = dayInt[2];
        LocalDate date = LocalDate.of(y, m, d);

        return date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
    }

    /**
     * 获取参照为指定日期的所属自然月第一天
     *
     * @param day 日期
     * @return 对应的日期
     */
    public static LocalDate getFirstDayOfMonth(Date day) {
        String[] dayStr = DateUtil.formatDate(day).split("-");
        Integer[] dayInt = Stream.of(dayStr).map(Integer::valueOf).toArray(Integer[]::new);
        Integer y = dayInt[0];
        Integer m = dayInt[1];
        Integer d = dayInt[2];
        LocalDate date = LocalDate.of(y, m, d);

        return date.with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 获取参照为今天的某一天日期-[指定格式化字符串]
     *
     * @param days 相差天数
     * @return 对应的日期字符串-[指定格式化字符串]
     */
    public static String getDateFormatOfDays(int days, String format) {
        LocalDate date = getDateOfDays(days);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); // 定义日期格式
        return date.format(formatter);
    }

    /**
     * map to bean方法
     *
     * @param map   map
     * @param clazz bean.class
     * @param <T>   bean
     * @return bean
     */
    public static <T> T mapToBean(Map<String, ?> map, Class<T> clazz) {
        T obj = null;
        try {
            obj = clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        if (obj != null) {
            for (Entry<String, ?> entry : map.entrySet()) {
                String key = entry.getKey();
                if (key != null) {
                    String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
                    try {
                        Method method = obj.getClass().getMethod(methodName, entry.getValue().getClass());
                        method.invoke(obj, entry.getValue());
                    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return obj;
    }


    public static LocalDateTime dateStringToLocalDateTime(String dateString) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return LocalDateTime.parse(dateString, formatter);
    }

//    /**
//     * 分页结果封装
//     *
//     * @param count    总条数
//     * @param dataList 数据list
//     * @param <T>      vo泛型
//     * @return voList
//     */
//    public static <T> CommonPage<T> setPage(Integer count, List<T> dataList) {
//        CommonPage<T> commonPage = new CommonPage<>();
//
//        //总条数
//        commonPage.setPageCount(count);
//        //数据list
//        commonPage.setDataList(dataList);
//
//        return commonPage;
//    }

    /**
     * 分页结果封装(iot)
     *
     * @param count    总条数
     * @param dataList 数据list
     * @param <T>      vo泛型
     * @return voList
     */
    public static <T> PageResult<T> setPage(Long count, List<T> dataList) {
        PageResult<T> pageResult = new PageResult<>();

        //总条数
        pageResult.setTotal(count);
        //数据list
        pageResult.setList(dataList);

        return pageResult;
    }


    public static void main(String[] args) throws Exception {
        String url = "http://127.0.0.1:7308/deviceoperate/CompassViewService/productCategoryView";
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("unitId", "10000");
        paramMap.put("accessstatus", "0");
        paramMap.put("statisticsTime", "2023-09-19");
        paramMap.put("topTab", "1");
        paramMap.put("secondTab", "1");
        paramMap.put("isBelowStandard", "0");
        Map<String, String> headMap = new HashMap<>();
        headMap.put("Content-Type", "application/json");
        String result = doHttpPost(url, paramMap, headMap);
        System.out.println("doHttpPost >>>> " + JSONObject.toJSON(result));
    }


}